package raytracergui;

import java.io.FilterOutputStream.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.ini4j.*;
import java.awt.Toolkit;
import java.awt.Dimension;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;


public class Application extends JFrame {

    private MenuBar         mnubMenu;
    private Menu            mnuFichier;
    private Menu            mnuAide;
    private MenuItem        mnuiCharger;
    private MenuItem        mnuiSauver;
    private MenuItem        mnuiQuitter;
    private MenuItem        mnuiAide;
    private MenuItem        mnuiStats;
    private MenuItem        mnuiApropos;

    private EventManager    eventMan;
    public  String          programme;
    private String          size;
    private String          factor;
    private String          depth;
    private Pouet           pane;
    private Image           image;
    private ArrayList       arObjets;
    private ArrayList       arLights;

    public Application() {
        
        
        eventMan = new EventManager();
        setTitle("Ray-a-lity");
        setSize(800, 600);
        addMenu(createMainMenu());
        setResizable(false);

        pane = new Pouet(this);

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
        setContentPane(pane);
        pane.setVisible(true);
        pane.VisAll(false);
        this.validate();



        // Get the size of the screen
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();

        // Determine the new location of the window
        int w = getSize().width;
        int h = getSize().height;
        int x = (dim.width - w) / 2;
        int y = (dim.height - h) / 2;

        // Move the window
        setLocation(x, y);

        
        
    }

    public MenuBar createMainMenu(){
        mnubMenu            = new MenuBar();

        mnuFichier          = new Menu("Fichier");
        mnuiCharger         = new MenuItem("Charger config...");
        mnuiSauver          = new MenuItem("Sauver config...");
        mnuiQuitter         = new MenuItem("Quitter");

        mnuAide             = new Menu("?");
        mnuiApropos         = new MenuItem("A propos");

        mnubMenu.add(mnuFichier);
        mnubMenu.add(mnuAide);

        mnuFichier.add(mnuiCharger);
        mnuFichier.add(mnuiSauver);
        mnuFichier.add(mnuiQuitter);

        mnuAide.add(mnuiApropos);

        mnuiCharger.addActionListener(eventMan);
        mnuiSauver.addActionListener(eventMan);
        mnuiQuitter.addActionListener(eventMan);
        mnuiApropos.addActionListener(eventMan);

        return mnubMenu;
    }

    public void addMenu(MenuBar menu)
    {
        this.setMenuBar(menu);
    }

    public boolean isNum(String s) {
        try {
            Double.parseDouble(s);
        }
            catch (NumberFormatException nfe) {
            return false;
        }
        return true;
    }

    public void ChargerConfigFile() throws IOException {
        String cheminFichier;
        image = new Image();
        arObjets = new ArrayList();
        arLights = new ArrayList();
        JFileChooser chooser = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter(
            "Fichiers .ini", "ini");
        chooser.setFileFilter(filter);
        int returnVal = chooser.showOpenDialog(null);
        if(returnVal == JFileChooser.APPROVE_OPTION) {
           System.out.println("Load: " + chooser.getSelectedFile().getAbsolutePath());
           cheminFichier = chooser.getSelectedFile().getAbsolutePath();

           Ini ini = new Ini();
           ini.load(new FileReader(cheminFichier));

           Ini.Section RaytracerOutputSection = ini.get("RaytracerOutput");

           size      = RaytracerOutputSection.get("size");
           String[] dims = size.split(",");
           image.setSizeX(dims[0]);
           image.setSizeY(dims[1]);
           factor    = RaytracerOutputSection.get("factor");
           image.setFactor(factor);
           depth     = RaytracerOutputSection.get("depth");
           image.setDepth(depth);

           Ini.Section SceneSection = ini.get("scene");

           String objects   = SceneSection.get("objects");
           String lights    = SceneSection.get("lights");

           Ini.Section visibleObject;
           Ini.Section visibleLight;
           String objectType;

           //[\s]+|,|;|=
           String[] objectsVisibles = objects.split(";");//on veut pas les commentaires
           objectsVisibles = objectsVisibles[0].split(",");//on veut les valeurs

           for(int i = 0;i<objectsVisibles.length;i++){
               visibleObject = ini.get(objectsVisibles[i]);
               System.out.println("Visible: "+objectsVisibles[i]);
               objectType = visibleObject.get("type");
               if(objectType.equals("Sphere")){
                    Sphere sphere   = new Sphere(objectsVisibles[i]);

                    String[] pos    = visibleObject.get("pos").split(";");
                    pos             = pos[0].split(",");
                    sphere.setPosition(pos[0],pos[1],pos[2]);

                    String[] radius    = visibleObject.get("radius").split(";");
                    sphere.setRadius(radius[0]);

                    String[] material    = visibleObject.get("material").split(";");
                    material             = material[0].split(",");
                    sphere.setMaterial(material[0],material[1],material[2],
                                        material[3],material[4],material[5],material[6]);
                    arObjets.add(sphere);
               }

               if(objectType.equals("Plane")){
                    Plane plane   = new Plane(objectsVisibles[i]);

                    String[] pos    = visibleObject.get("pos").split(";");
                    pos             = pos[0].split(",");
                    plane.setPosition(pos[0],pos[1],pos[2]);

                    String[] up    = visibleObject.get("up").split(";");
                    up             = up[0].split(",");
                    plane.setUp(up[0],up[1],up[2]);

                    String[] material    = visibleObject.get("material").split(";");
                    material             = material[0].split(",");
                    plane.setMaterial(material[0],material[1],material[2],
                                        material[3],material[4],material[5],material[6]);
                    arObjets.add(plane);
               }
           }


           String[] lightsVisibles  = lights.split(";");//on veut pas les commentaires
           lightsVisibles = lightsVisibles[0].split(",");//on veut les valeurs
           for(int i = 0;i<lightsVisibles.length;i++){
                visibleLight = ini.get(lightsVisibles[i]);

                Light light     = new Light(lightsVisibles[i]);
                String[] pos    = visibleLight.get("pos").split(";");
                pos             = pos[0].split(",");
                light.setPosition(  pos[0],pos[1],pos[2]);

                String[] couleur    = visibleLight.get("color").split(";");
                couleur             = couleur[0].split(",");
                light.setCouleur(couleur[0],couleur[1],couleur[2]);
                arLights.add(light);
           }

           Set setSections  = ini.keySet();
           Iterator itr     = setSections.iterator();
           while(itr.hasNext()){
                String quoi = (String) itr.next();
                System.out.println("Section: "+quoi);
           }

        }

        pane.setList(arObjets,arLights);
        UpdateGUI();
    }

    public void UpdateGUI(){
        System.out.println("ug called");

        pane.VisAll(false);
        pane.VisjTImgX(true);
        pane.VisjTImgY(true);
        pane.VisjTImgZ(true);
        pane.VisjTFact(true);
        pane.setjTImgX(image.getSizeX());
        pane.setjTImgY(image.getSizeY());
        pane.setjTImgZ(image.getDepth());
        pane.setjTFact(image.getFactor());

        Object selObj = pane.getjList().getSelectedValue();

        if(selObj instanceof Sphere){
            Sphere sphObj = (Sphere) selObj;
            pane.setjTX(sphObj.getPosX());
            pane.setjTY(sphObj.getPosY());
            pane.setjTZ(sphObj.getPosZ());
            pane.setjTRadius(sphObj.getRadius());
            pane.setjTMatR(sphObj.getMatR());
            pane.setjTMatG(sphObj.getMatG());
            pane.setjTMatB(sphObj.getMatB());
            pane.setjTMatDiffu(sphObj.getMatDiffuse());
            pane.setjTMatSpec(sphObj.getMatSpecular());
            pane.setjTMatRefl(sphObj.getMatReflective());
            pane.setjTMatDiffr(sphObj.getMatDiffraction());

            pane.VisjTX(true);
            pane.VisjTY(true);
            pane.VisjTZ(true);
            pane.VisjTRadius(true);
            pane.VisjTMatR(true);
            pane.VisjTMatG(true);
            pane.VisjTMatB(true);
            pane.VisjTMatDiffu(true);
            pane.VisjTMatSpec(true);
            pane.VisjTMatRefl(true);
            pane.VisjTMatDiffr(true);

        }
        if(selObj instanceof Plane){
            Plane plaObj = (Plane) selObj;
            pane.setjTX(plaObj.getPosX());
            pane.setjTY(plaObj.getPosY());
            pane.setjTZ(plaObj.getPosZ());
            pane.setjTMatR(plaObj.getMatR());
            pane.setjTMatG(plaObj.getMatG());
            pane.setjTMatB(plaObj.getMatB());
            pane.setjTMatDiffu(plaObj.getMatDiffuse());
            pane.setjTMatSpec(plaObj.getMatSpecular());
            pane.setjTMatRefl(plaObj.getMatReflective());
            pane.setjTMatDiffr(plaObj.getMatDiffraction());
            pane.setjTHautX(plaObj.getUpX());
            pane.setjTHautY(plaObj.getUpY());
            pane.setjTHautZ(plaObj.getUpZ());

            pane.VisjTX(true);
            pane.VisjTY(true);
            pane.VisjTZ(true);
            pane.VisjTMatR(true);
            pane.VisjTMatG(true);
            pane.VisjTMatB(true);
            pane.VisjTMatDiffu(true);
            pane.VisjTMatSpec(true);
            pane.VisjTMatRefl(true);
            pane.VisjTMatDiffr(true);
            pane.VisjTHautX(true);
            pane.VisjTHautY(true);
            pane.VisjTHautZ(true);
        }
        if(selObj instanceof Light){
            Light lightObj = (Light) selObj;
            pane.setjTColB(lightObj.getCouleurB());
            pane.setjTColR(lightObj.getCouleurR());
            pane.setjTColG(lightObj.getCouleurG());
            pane.setjTX(lightObj.getPosX());
            pane.setjTY(lightObj.getPosY());
            pane.setjTZ(lightObj.getPosZ());

            pane.VisjTColR(true);
            pane.VisjTColG(true);
            pane.VisjTColB(true);
            pane.VisjTX(true);
            pane.VisjTY(true);
            pane.VisjTZ(true);
        }

        pane.revalidate();
    }

    public void SauverConfigFile(){
        String cheminFichier;
        int i=0;
        JFileChooser chooser = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter(
            "Fichiers .ini", "ini");
        chooser.setFileFilter(filter);
        int returnVal = chooser.showSaveDialog(null);
        if(returnVal == JFileChooser.APPROVE_OPTION) {
            try {
                cheminFichier = chooser.getSelectedFile().getAbsolutePath();
                Ini ini = new Ini();


                Ini.Section RaytracerOutputSection = ini.add("RaytracerOutput");
                RaytracerOutputSection.add("size", image.getSizeX()+","+image.getSizeY());
                RaytracerOutputSection.add("factor", image.getFactor());
                RaytracerOutputSection.add("depth", image.getDepth());

                Ini.Section SceneSection = ini.add("scene");
                String temp = "";
                for(i=0;i<this.arObjets.size();i++){
                    temp += this.arObjets.get(i).toString();
                    if(i == this.arObjets.size()-1) break;
                    temp += ",";
                }
                SceneSection.add("objects", temp);

                temp="";
                for(i=0;i<this.arLights.size();i++){
                    temp += this.arLights.get(i).toString();
                    if(i == this.arLights.size()-1) break;
                    temp += ",";
                }
                SceneSection.add("lights", temp);
                
                for(i=0;i<this.arObjets.size();i++){
                    SceneSection = ini.add(this.arObjets.get(i).toString());
                    if(this.arObjets.get(i) instanceof Sphere){
                        Sphere sphere = (Sphere) this.arObjets.get(i);
                        SceneSection.add("type", "Sphere");
                        SceneSection.add("pos",sphere.getPosX()+","+sphere.getPosY()+","+sphere.getPosZ());
                        SceneSection.add("radius", sphere.getRadius());
                        SceneSection.add("material",sphere.getMatR()+","+
                                                    sphere.getMatG()+","+
                                                    sphere.getMatB()+","+
                                                    sphere.getMatDiffuse()+","+
                                                    sphere.getMatSpecular()+","+
                                                    sphere.getMatReflective()+","+
                                                    sphere.getMatDiffraction());
                    }else
                    if(this.arObjets.get(i) instanceof Plane){
                        Plane plane = (Plane) this.arObjets.get(i);
                        SceneSection.add("type", "Plane");
                        SceneSection.add("pos",plane.getPosX()+","+plane.getPosY()+","+plane.getPosZ());
                        SceneSection.add("up", plane.getUpX()+","+plane.getUpY()+","+plane.getUpZ());
                        SceneSection.add("material",plane.getMatR()+","+
                                                    plane.getMatG()+","+
                                                    plane.getMatB()+","+
                                                    plane.getMatDiffuse()+","+
                                                    plane.getMatSpecular()+","+
                                                    plane.getMatReflective()+","+
                                                    plane.getMatDiffraction());
                    }
                }
                
                for(i=0;i<this.arLights.size();i++){
                    SceneSection = ini.add(this.arLights.get(i).toString());
                    if(this.arLights.get(i) instanceof Light){
                        Light light = (Light) this.arLights.get(i);
                        SceneSection.add("pos",light.getPosX()+","+light.getPosY()+","+light.getPosZ());
                        SceneSection.add("color", light.getCouleurR()+","+light.getCouleurG()+","+light.getCouleurB());
                    }
                }

                ini.store(new FileWriter(cheminFichier));

            } catch (Exception ex) {
                Logger.getLogger(Application.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public ArrayList getArLights() {
        return arLights;
    }

    public ArrayList getArObjets() {
        return arObjets;
    }

    public Image getImage() {
        return image;
    }



    public class EventManager implements ActionListener
    {
        public void actionPerformed(ActionEvent ae)
        {
            if (ae.getSource() == mnuiQuitter) {
                if (JOptionPane.showConfirmDialog(null, "Êtes-vous sûr de vouloir quitter le programme?",
                        "Réfléchissez bien...", JOptionPane.YES_NO_OPTION) == 0)
                    System.exit(0);
            } else if (ae.getSource() == mnuiApropos) {
                JOptionPane.showMessageDialog(null, "Auteurs du programme:\nEmmanuel Bengio\n" +
                        "Phillippe Nadeau\nGauthier Viau", "A propos...",
                        JOptionPane.INFORMATION_MESSAGE);
            } else if (ae.getSource() == mnuiCharger) {
                try {
                    //Charger fichier config
                    ChargerConfigFile();
                } catch (IOException ex) {
                    Logger.getLogger(Application.class.getName()).log(Level.SEVERE, null, ex);
                }
            } else if (ae.getSource() == mnuiSauver) {
                //Sauver options dans fichier config
                SauverConfigFile();
            }
        }
    }
}